package std

import (
	"errors"
	"fmt"
	"gitee.com/youbeiwuhuan/gin-practice/go-err/std/simple"
)

var (
	ErrUserNotFound = errors.New("user not found")
)

func IsE() {
	/// 错误匹配：Is 函数
	//errors.Is 函数用于判断两个 error 是否相等，通常用于检查一个错误链中是否包含某个特定的错误。当一个错误被包装多层时，该函数将会递归检查错误链的每一层，确定是否存在与目标错误相等的错误。
	//
	//errors.Is 函数的签名如下：
	//
	//func Is(err, target error) bool
	//参数：
	//err 为要检查的错误。
	//target 为目标错误。errors.Is 函数会检查 err 是否等于 target，或 err 链中是否存在一个错误等于 target。
	//返回值：返回一个 bool 类型的值。如果两个 error 相等，返回 true，否则返回 false。

	err := fmt.Errorf("%w: name=%s", ErrUserNotFound, "陈明勇")
	if errors.Is(err, ErrUserNotFound) {
		fmt.Println("error is ErrUserNotFound")
	} else {
		fmt.Println(err)
	}
}

func AsE() {
	/// 错误断言：As 函数
	//errors.As 函数用于检查一个错误是否可以被断言为特定的错误类型，断言成功则将错误的值赋给特定的错误变量。
	//
	//errors.As 函数的签名如下：
	//
	//func As(err error, target any) bool
	//参数：
	//err 为被断言的错误。
	//target 为目标错误，它必须是一个非空指针。
	//返回值：返回一个 bool 类型的值。如果断言成功，返回 true，否则返回 false。
	//下面是 As 函数的代码使用示例：

	var err = &simple.UserNotError{Name: "陈明勇"}
	var errUserNotFound = &simple.UserNotError{}
	if errors.As(err, &errUserNotFound) {
		fmt.Println(errUserNotFound.Name) // 陈明勇
	} else {
		fmt.Println(err)
	}
}

func JoinE() {
	/// 包装错误：Join 函数
	//errors.Join 是 Go 1.20 版本新增的一个函数，该函数用于包装（合并）给定的 errs（错误集） 并返回一个新的错误对象。当 errs 为 nil 时，errors.Join 函数返回 nil。需要注意的是 errors.Join 在包装 error 的过程中，会忽略 nil error。
	//
	//errors.Join 函数的签名如下：
	//
	//func Join(errs ...error) error
	//其中：
	//
	//参数：errs 为所给定的错误集。
	//返回值：返回一个 error 接口类型的对象，其值为包装后的新 error。

	err1 := errors.New("error 1")
	err2 := errors.New("error 2")
	err := errors.Join(err1, err2)
	fmt.Println(err)
	fmt.Println(errors.Is(err, err1)) // true
	fmt.Println(errors.Is(err, err2)) // true
}

func UnwrapE() {
	/// 获取原始错误：Unwrap 函数
	//errors.Unwrap 函数用于获取一个包装过的 error 值的原始 error，它接收一个 err error 参数。
	//
	//errors.Unwrap 函数的签名如下：
	//
	//func Unwrap(err error) error
	//其中：
	//
	//参数：err 为所给定的错误。
	//返回值：返回一个 error 类型的对象。其值为解包后的 error。

	err := fmt.Errorf("%w: name=%s", ErrUserNotFound, "陈明勇")
	fmt.Println(err)
	fmt.Println(errors.Unwrap(err))
}
